#include "lang.h"

static void outputPremble(FILE *f)
{
    fputs("#ifndef __TREE_ACCESS_H_\n"
          "#define __TREE_ACCESS_H_\n"
          "\n"
          "#include \"config.h\"\n"
          "\n"
          "#ifdef ENABLE_TREE_CHECKS\n"
          "#define TREE_CHECK(obj, type)                                   \\\n"
          "          (tree_check((obj), (type), __FILE__, __LINE__, __func__))\n"
          "#else\n"
          "#define TREE_CHECK(obj, type) (obj)\n"
          "#endif\n"
          "\n", f);
}

static void outputProps(FILE *f, const struct TreeType &t)
{
    if (t.props.size() == 0)
        return;

    fprintf(f, "/* Access macros for %s objects */\n", t.name.c_str());

    for (const auto prop : t.props)
        fprintf(f, "#define %s(obj) (_DATA( TREE_CHECK((obj), %s)).%s)\n",
                t.getPropAccessor(prop.first).c_str(), t.name.c_str(),
                prop.second.memberName.c_str());

    fprintf(f,"\n");
}

static void outputTreeAccessMacros(const struct lang &lang,
                                   FILE *f)
{
    for (const auto type : lang.treeTypes)
        outputProps(f, type);

    for (const auto ctype : lang.treeCTypes)
        outputProps(f, ctype);
}

static void outputEpilogue(FILE *f)
{
    fputs("#endif\n", f);
}


static void usage(char *progname)
{
    fprintf(stderr, "%s - Generate the `tree-access.h' file from a language description\n",
            progname);
    fprintf(stderr, "Usage: %s LANG_DESC_FILE\n", progname);
    fprintf(stderr, "\n");
    fprintf(stderr, "Where LANG_DESC_FILE is a language description file.\n");
}

int main(int argc, char *argv[])
{
    struct lang lang;
    FILE *f;

    if (argc != 2) {
        fprintf(stderr, "Error: %s expects exactly one argument\n", argv[0]);
        usage(argv[0]);
        return 1;
    }

    f = fopen(argv[1], "r");

    if (!f) {
        perror("Could not open lang file");
        usage(argv[0]);
        exit(2);
    }

    lang_read(f, lang);

    FILE *output = fopen("tree-access.h", "w");

    fputs("/*\n"
          " * tree-access.h - Tree data access macros.\n"
          " *\n"
          " * Automatically generated by genaccess. DO NOT EDIT.\n"
          " */\n\n", output);

    outputPremble(output);
    outputTreeAccessMacros(lang, output);
    outputEpilogue(output);

    fclose(output);

    return 0;
}
